package daobeauty.interceptor.invoke.impl;

import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import daobeauty.interceptor.invoke.AbstractCurrentSessionInvokeStrategy;
import daobeauty.util.MethodSignatureUtils;

public class GetNamedQueryInvoke extends AbstractCurrentSessionInvokeStrategy {
	private static final Log LOG = LogFactory.getLog(GetNamedQueryInvoke.class);
	
	public GetNamedQueryInvoke(Method method, SessionFactory sessionFactory, Class domainClass) {
		super(sessionFactory, domainClass);
		final Class [] parameterTypes = method.getParameterTypes();
		if (parameterTypes==null || parameterTypes.length!=1 || !String.class.isAssignableFrom(parameterTypes[0])){
			throw new IllegalArgumentException("method "+MethodSignatureUtils.toMethodSignature(method)+" must have exactly one string parameter: the name of the named query.");
		}
		final Class returnType = method.getReturnType();
		if (returnType==null || !Query.class.isAssignableFrom(returnType)){
			throw new IllegalArgumentException("method "+MethodSignatureUtils.toMethodSignature(method)+" must have return type compatible with "+Query.class.getName());
		}
		if (LOG.isInfoEnabled()){
			LOG.info("created getNamedQuery strategy for method "+MethodSignatureUtils.toMethodSignature(method));
		}
	}
	
	public Object invoke(String methodName, Object[] args) throws Exception {
		if (args[0]==null){
			throw new NullPointerException("\"getNamedQuery\" with parameter null invoked");
		}
		
		return getNamedQuery((String) args[0], getDomainClass(), getCurrentSession());
	}
	
	public static final Query getNamedQuery(String queryName, Class domainClass, Session currentSession){
		if (LOG.isDebugEnabled()){
			LOG.debug("getNamedQuery("+queryName+")");
		}
		Query query = null;
		try{
			// a. namedquery speziell fuer domain (in domain mapping konfiguration)
			query = currentSession.getNamedQuery(domainClass.getName()+"."+queryName);
		}
		catch(MappingException e){
			// no such named query
			query =  null;
		}
		if (query==null){
			try{
				// b. namedquery generell (in generaller mapping konfiguration)
				query = currentSession.getNamedQuery(queryName);
			}
			catch(MappingException e){
				// no such named query
				query =  null;
			}
		}
		return query;
	}
}
